package com.winning.java.threads;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.scheduling.config.Task;

import java.io.Console;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author: rqx
 * @create: 2023/6/5 10:32
 * @description:
 */
@Slf4j
public class Main {
    @SneakyThrows
    @Test
    public void TaskTest1() {
        new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    Thread.sleep(50);
                    log.info("{}", i);
                }
                log.info("Task finish");
            }
        }).start();
        Thread.sleep(200);
        log.info("finish");
    }

    @SneakyThrows
    @Test
    public void TaskTest2() {
        var t = MyThread.run(() -> {
            for (var i = 0; i < 10; i++) {
                Thread.sleep(50);
                log.info("{}", i);
            }
            log.info("Task finish");
        });
        t.start();

        Thread.sleep(200);
        log.info("finish");
        t.join();
    }

    @SneakyThrows
    @Test
    public void TaskTest3() {
        var t1 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    Thread.sleep(50);
                    log.info("{}", i);
                }
                log.info("Task1 finish");
            }
        });
        t1.start();
        var t2 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    Thread.sleep(50);
                    log.info("{}", (char) ('a' + i));
                }
                log.info("Task2 finish");
            }
        });
        t2.start();

        Thread.sleep(200);
        t1.join();
        t2.join();
        log.info("finish");
    }

    @SneakyThrows
    @Test
    public void TaskTest4() {
        final int[] num = {0};
        var t1 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    var tmp = num[0];
                    Thread.sleep(30);
                    num[0] = tmp + 1;
                    log.info("Task1 {} : {}", i, num[0]);
                }
                log.info("Task1 finish");
            }
        });
        t1.start();
        var t2 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    var tmp = num[0];
                    Thread.sleep(20);
                    num[0] = tmp - 1;
                    log.info("Task2 {} : {}", i, num[0]);
                }
                log.info("Task2 finish");
            }
        });
        t2.start();

        Thread.sleep(200);
        t1.join();
        t2.join();
        log.info("finish obj:{}", num[0]);
    }

    @SneakyThrows
    @Test
    public void TaskTest5() {
        var obj = new Object();
        final int[] num = {0};
        var t1 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    synchronized (obj) {
                        var tmp = num[0];
                        Thread.sleep(30);
                        num[0] = tmp + 1;
                        log.info("Task1 {} : {}", i, num[0]);
                    }
                    Thread.sleep(30);
                }
                log.info("Task1 finish");
            }
        });
        t1.start();
        var t2 =new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    synchronized (obj) {
                        var tmp = num[0];
                        Thread.sleep(20);
                        num[0] = tmp - 1;
                        log.info("Task2 {} : {}", i, num[0]);
                    }
                    Thread.sleep(20);
                }
                log.info("Task2 finish");
            }
        });
        t2.start();

        Thread.sleep(200);
        t1.join();
        t2.join();
        log.info("finish obj:{}", num[0]);
    }

    @SneakyThrows
    @Test
    public void TaskTest6() {
        var sema = new Semaphore(1, true);
        final int[] num = {0};
        var t1 =new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    sema.acquire();
                    var tmp = num[0];
                    Thread.sleep(30);
                    num[0] = tmp + 1;
                    log.info("Task1 {} : {}", i, num[0]);
                    sema.release();
                }
                log.info("Task1 finish");
            }
        });
        t1.start();
        var t2 =new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                for (var i = 0; i < 10; i++) {
                    sema.acquire();
                    var tmp = num[0];
                    Thread.sleep(20);
                    num[0] = tmp - 1;
                    log.info("Task2 {} : {}", i, num[0]);
                    sema.release();
                }
                log.info("Task2 finish");
            }
        });
        t2.start();

        Thread.sleep(200);

        t1.join();
        t2.join();
        log.info("finish obj:{}", num[0]);
    }
}
